﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using STSdb.MTL.Utils.Serialization;

namespace STSdb.MTL
{
    /// <summary>
    /// RemoteCommandsCoordinator Executes different commands through different engine instances.
    /// All parameters are sent as strings, result is also string.
    /// </summary>
    public class RemoteCommandsCoordinator
    {

        /// <summary>
        /// Returns serialized List of Strings - result of sequential command execution
        /// </summary>
        /// <param name="cmds"></param>
        /// <returns></returns>
        public string ExecuteCommands(List<RemoteCommand> cmds)
        {
            List<string> rets = new List<string>();

            Dictionary<string, Transaction> transactions = new Dictionary<string, Transaction>();

            Transaction transaction = null;
            STSdbMTLengine engine = null;

            foreach (var rc in cmds)
            {
                try
                {
                    if (!transactions.TryGetValue(rc.EngineName, out transaction))
                    {
                        engine = Engines.GetEngine(rc.EngineName);

                        if (engine == null)
                        {
                            rets.Add("@@engineNotFound@@" + rc.EngineName);
                            continue;
                        }
                        else
                        {
                            transaction = engine.GetTransaction();
                            transactions.Add(rc.EngineName, transaction);
                        }
                    }

                    //doing operations with transactions (for one engine one transaction is used)
                    rets.Add(GetCommandResult(transaction, rc));
                }
                catch (Exception ex)
                {
                    rets.Add("@@Exception@@" + ex.ToString());
                }

            }


            return rets.SerializeXml();
        }


        /// <summary>
        /// Executes one command and returns string result of its execution
        /// </summary>
        /// <param name="cmd"></param>
        /// <returns></returns>
        public string ExecuteCommand(RemoteCommand cmd)
        {
            string res = "@@void@@";

            try
            {
                var engine = Engines.GetEngine(cmd.EngineName);

                if (engine == null)
                    return "@@engineNotFound@@" + cmd.EngineName;

                using (var tran = engine.GetTransaction())
                {
                    return GetCommandResult(tran, cmd);
                }
            }
            catch (Exception ex)
            {
                res = "@@Exception@@" + ex.ToString();
            }


            return res;
        }



        /// <summary>
        /// Commands processor
        /// </summary>
        /// <param name="tran"></param>
        /// <param name="cmd"></param>
        /// <returns></returns>
        private string GetCommandResult(Transaction tran, RemoteCommand cmd)
        {
            switch (cmd.Command.ToUpper())
            {
                case "SELECT":

                    return tran.NonGenerics.Select(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], cmd.Parameters[4]);

                case "SELECTFORWARD":

                    return tran.NonGenerics.SelectForward(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], Convert.ToInt32(cmd.Parameters[4]));

                case "SELECTFORWARDSTARTENDKEY":

                    return tran.NonGenerics.SelectForwardStartEndKey(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], cmd.Parameters[4], cmd.Parameters[5], Convert.ToInt32(cmd.Parameters[6]));

                case "SELECTFORWARDSTARTKEY":

                    return tran.NonGenerics.SelectForwardStartKey(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], cmd.Parameters[4], Convert.ToInt32(cmd.Parameters[5]));

                case "SELECTBACKWARD":

                    return tran.NonGenerics.SelectBackward(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], Convert.ToInt32(cmd.Parameters[4]));

                case "SELECTBACKWARDLASTFIRSTKEY":

                    return tran.NonGenerics.SelectBackwardLastFirstKey(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], cmd.Parameters[4], cmd.Parameters[5], Convert.ToInt32(cmd.Parameters[6]));

                case "SELECTBACKWARDLASTKEY":

                    return tran.NonGenerics.SelectBackwardLastKey(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3], cmd.Parameters[4], Convert.ToInt32(cmd.Parameters[5]));

                case "COUNT":

                    return tran.NonGenerics.Count(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3]);

                case "MAXROW":

                    return tran.NonGenerics.MaxRow(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3]);

                case "MINROW":

                    return tran.NonGenerics.MinRow(cmd.Parameters[0], Type.GetType(cmd.Parameters[1]), Type.GetType(cmd.Parameters[2]), cmd.Parameters[3]);

                case "GETALLTABLESNAMES":

                    return tran.NonGenerics.GetAllTablesNames();

                default:

                    return "@@unrecognizedCommand@@";
            }
        }




        

    }
}
